package com.hyjx.framework.component.operatelog;

import com.alibaba.fastjson.JSON;
import com.hyjx.framework.common.CommonUtil;
import com.hyjx.framework.common.util.StringHelper;
import com.hyjx.framework.component.operatelog.operatelogdetail.OperatelogDetailModel;
import com.hyjx.framework.orm.dao.IBaseDao;
import com.hyjx.framework.service.ConfigManager;
import com.hyjx.framework.service.SystemService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * baseDao 的切面类
 */
@Aspect
@Component
public class BaseDaoAspect {
    private static Logger logger = LoggerFactory.getLogger(BaseDaoAspect.class);
    
    @Resource
    private IBaseDao dao;
    
    @Pointcut("within(@org.springframework.stereotype.Repository *)")
    private void anymethod() {
    }
    
    @Before("anymethod()")
    public void before() {
        OperatelogStatus.start = System.currentTimeMillis();
    }
    
    @After("anymethod()")
    public void after() {
        OperatelogStatus.end = System.currentTimeMillis();
    }
    
    @Around("anymethod()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        if ("1".equals(SystemService.getSysInitStatus())) {
            return joinPoint.proceed();
        }
        Object obj = null;
        Object[] os = joinPoint.getArgs();
        if (os[0] != null && os[0].toString().startsWith("logbusinessdata.")) {
            return joinPoint.proceed();
        }
        String operatelog = ConfigManager.getConfig("operatelog");
        if (operatelog != null && operatelog.equals("1")) {
            if (joinPoint.getStaticPart().toString().indexOf(".updateObject") > -1) {
                this.addoplog(String.valueOf(os[0]), os[1], true);
                obj = joinPoint.proceed();
                this.addoplog(String.valueOf(os[0]), os[1], false);
            } else if (joinPoint.getStaticPart().toString().indexOf(".addObject") > -1
                    || joinPoint.getStaticPart().toString().indexOf("nsertObject") > -1) {
                try {
                    obj = joinPoint.proceed();
                } catch (Exception e) {
                    logger.debug("日志保存失败", e);
                }
                this.addoplog(String.valueOf(os[0]), os[1], false);
            } else if (joinPoint.getStaticPart().toString().indexOf(".deleteObject") > -1) {
                this.addoplog(String.valueOf(os[0]), os[1], true);
                obj = joinPoint.proceed();
            } else {
                obj = joinPoint.proceed();
            }
        } else {
            obj = joinPoint.proceed();
        }
        return obj;
    }
    
    /**
     * 增加日志
     *
     * @param sqlname
     * @param param
     * @param beforeupdate
     */
    @SuppressWarnings("unchecked")
    private void addoplog(String sqlname, Object param, boolean beforeupdate) {
        if (sqlname.indexOf("operatelog") > -1) {
            return;
        }
        if (OperatelogStatus.varServ == 0) {
            OperatelogStatus.varServ = OperatelogStatus.varCon;
            OperatelogModel olmodel = new OperatelogModel();
            olmodel.setOlogid(StringHelper.getPrimaryKey());
            OperatelogStatus.olid = olmodel.getOlogid();
            olmodel.setTimestamp(StringHelper.getDateTime());
            olmodel.setUser_id(OperatelogStatus.user_id);
            olmodel.setUrl(OperatelogStatus.url);
        } else {
            if (OperatelogStatus.varServ == OperatelogStatus.varCon) { //同一个操作
                //System.out.println("操作" + OperatelogStatus.varCon);
            } else {
                OperatelogStatus.varServ = OperatelogStatus.varCon;
                OperatelogModel olmodel = new OperatelogModel();
                olmodel.setOlogid(StringHelper.getPrimaryKey());
                OperatelogStatus.olid = olmodel.getOlogid();
                olmodel.setTimestamp(StringHelper.getDateTime());
                olmodel.setUser_id(OperatelogStatus.user_id);
                olmodel.setUrl(OperatelogStatus.url);
                dao.addObject(olmodel.getModuleName() + ".insert", olmodel);
                
            }
            try {
                OperatelogDetailModel odmodel = new OperatelogDetailModel();
                odmodel.setOlid(OperatelogStatus.olid);
                odmodel.setOdid(StringHelper.getPrimaryKey());
                odmodel.setSpendtime(String.valueOf(OperatelogStatus.end - OperatelogStatus.start));
                String sql = dao.getCurrSql(param, sqlname).trim();
                if (sql.toLowerCase().startsWith("insert")) {
                    try {
                        String tname = sql.substring(sql.toLowerCase().indexOf("into") + 4, sql.indexOf("(")).trim();
                        String where = " where " + sql.substring(sql.indexOf("(") + 1, sql.indexOf(",")) + "=" + sql.toLowerCase().split("values")[1].substring(sql.toLowerCase().split("values")[1].indexOf("(") + 1, sql.toLowerCase().split("values")[1].indexOf(","));
                        String sqlnewrec = "select * from " + tname + " " + where;
                        List<Map<String, String>> list = dao.queryObjectList(new OperatelogModel().getModuleName() + ".querymap", sqlnewrec);
                        String oldrec = JSON.toJSONString(list);
                        odmodel.setLastrec(oldrec);
                    } catch (IndexOutOfBoundsException e1) {
                    } catch (Exception e) {
                    }
                    
                } else if (sql.startsWith("delete")) {
                    try {
                        String tname = sql.substring(sql.toLowerCase().indexOf("from") + 5, sql.toLowerCase().indexOf(" where"));
                        String where = sql.substring(sql.toLowerCase().indexOf("where"), sql.length());
                        String sqloldrec = "select * from " + tname + " " + where;
                        List<Map<String, String>> list = dao.queryObjectList(new OperatelogModel().getModuleName() + ".querymap", sqloldrec);
                        String oldrec = JSON.toJSONString(list);
                        
                        odmodel.setOrigrec(oldrec);
                    } catch (IndexOutOfBoundsException e1) {
                    } catch (Exception e) {
                    }
                } else if (sql.startsWith("update")) {
                    if (beforeupdate) {
                        try {
                            String tname = sql.substring(6, sql.toLowerCase().indexOf("set")).trim();
                            String where = sql.substring(sql.toLowerCase().indexOf("where"), sql.length());
                            String sqloldrec = "select * from " + tname + " " + where;
                            List<Map<String, String>> list = dao.queryObjectList(new OperatelogModel().getModuleName() + ".querymap", sqloldrec);
                            String oldrec = JSON.toJSONString(list);
                            odmodel.setOrigrec(oldrec);
                            OperatelogStatus.tempolid = odmodel.getOdid();
                            OperatelogStatus.tempval = sqloldrec;
                        } catch (IndexOutOfBoundsException e1) {
                        } catch (Exception e) {
                        }
                    } else {
                        try {
                            if (StringUtils.isEmpty(OperatelogStatus.tempval)) return;
                            List<Map<String, String>> list = dao.queryObjectList(new OperatelogModel().getModuleName() + ".querymap", OperatelogStatus.tempval);
                            String newrec = CommonUtil.getJsonString(list);
                            odmodel.setLastrec(newrec);
                            odmodel.setOdid(OperatelogStatus.tempolid);
                            dao.updateObject(new OperatelogDetailModel().getModuleName() + ".update", odmodel);
                            OperatelogStatus.tempolid = OperatelogStatus.tempval = null;
                        } catch (IndexOutOfBoundsException e1) {
                        } catch (Exception e) {
                        }
                        return;
                    }
                }
                odmodel.setTimestamp(StringHelper.getDateTime());
                odmodel.setSql(sql);
                dao.addObject(new OperatelogDetailModel().getModuleName() + ".insert", odmodel);
            
            
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}